home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / Mail / head.c < prev    next >
C/C++ Source or Header  |  1990-02-08  |  5KB  |  233 lines

  1. /*
  2.  * Copyright (c) 1980 Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms are permitted
  6.  * provided that the above copyright notice and this paragraph are
  7.  * duplicated in all such forms and that any documentation,
  8.  * advertising materials, and other materials related to such
  9.  * distribution and use acknowledge that the software was developed
  10.  * by the University of California, Berkeley.  The name of the
  11.  * University may not be used to endorse or promote products derived
  12.  * from this software without specific prior written permission.
  13.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  14.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  15.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  16.  */
  17.  
  18. #ifndef lint
  19. static char sccsid[] = "@(#)head.c    5.6 (Berkeley) 7/8/88";
  20. #endif /* not lint */
  21.  
  22. #include "rcv.h"
  23.  
  24. /*
  25.  * Mail -- a mail program
  26.  *
  27.  * Routines for processing and detecting headlines.
  28.  */
  29.  
  30. /*
  31.  * See if the passed line buffer is a mail header.
  32.  * Return true if yes.  Note the extreme pains to
  33.  * accomodate all funny formats.
  34.  */
  35. ishead(linebuf)
  36.     char linebuf[];
  37. {
  38.     register char *cp;
  39.     struct headline hl;
  40.     char parbuf[BUFSIZ];
  41.  
  42.     cp = linebuf;
  43.     if (*cp++ != 'F' || *cp++ != 'r' || *cp++ != 'o' || *cp++ != 'm' ||
  44.         *cp++ != ' ')
  45.         return (0);
  46.     parse(linebuf, &hl, parbuf);
  47.     if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
  48.         fail(linebuf, "No from or date field");
  49.         return (0);
  50.     }
  51.     if (!isdate(hl.l_date)) {
  52.         fail(linebuf, "Date field not legal date");
  53.         return (0);
  54.     }
  55.     /*
  56.      * I guess we got it!
  57.      */
  58.     return (1);
  59. }
  60.  
  61. /*ARGSUSED*/
  62. fail(linebuf, reason)
  63.     char linebuf[], reason[];
  64. {
  65.  
  66.     /*
  67.     if (value("debug") == NOSTR)
  68.         return;
  69.     fprintf(stderr, "\"%s\"\nnot a header because %s\n", linebuf, reason);
  70.     */
  71. }
  72.  
  73. /*
  74.  * Split a headline into its useful components.
  75.  * Copy the line into dynamic string space, then set
  76.  * pointers into the copied line in the passed headline
  77.  * structure.  Actually, it scans.
  78.  */
  79. parse(line, hl, pbuf)
  80.     char line[], pbuf[];
  81.     register struct headline *hl;
  82. {
  83.     register char *cp;
  84.     char *sp;
  85.     char word[LINESIZE];
  86.  
  87.     hl->l_from = NOSTR;
  88.     hl->l_tty = NOSTR;
  89.     hl->l_date = NOSTR;
  90.     cp = line;
  91.     sp = pbuf;
  92.     /*
  93.      * Skip over "From" first.
  94.      */
  95.     cp = nextword(cp, word);
  96.     cp = nextword(cp, word);
  97.     if (*word)
  98.         hl->l_from = copyin(word, &sp);
  99.     if (cp != NOSTR && cp[0] == 't' && cp[1] == 't' && cp[2] == 'y') {
  100.         cp = nextword(cp, word);
  101.         hl->l_tty = copyin(word, &sp);
  102.     }
  103.     if (cp != NOSTR)
  104.         hl->l_date = copyin(cp, &sp);
  105. }
  106.  
  107. /*
  108.  * Copy the string on the left into the string on the right
  109.  * and bump the right (reference) string pointer by the length.
  110.  * Thus, dynamically allocate space in the right string, copying
  111.  * the left string into it.
  112.  */
  113. char *
  114. copyin(src, space)
  115.     register char *src;
  116.     char **space;
  117. {
  118.     register char *cp;
  119.     char *top;
  120.  
  121.     top = cp = *space;
  122.     while (*cp++ = *src++)
  123.         ;
  124.     *space = cp;
  125.     return (top);
  126. }
  127.  
  128. /*
  129.  * Test to see if the passed string is a ctime(3) generated
  130.  * date string as documented in the manual.  The template
  131.  * below is used as the criterion of correctness.
  132.  * Also, we check for a possible trailing time zone using
  133.  * the tmztype template.
  134.  */
  135.  
  136. /*
  137.  * 'A'    An upper case char
  138.  * 'a'    A lower case char
  139.  * ' '    A space
  140.  * '0'    A digit
  141.  * 'O'    An optional digit or space
  142.  * ':'    A colon
  143.  * 'N'    A new line
  144.  */
  145. char ctype[] = "Aaa Aaa O0 00:00:00 0000";
  146. char tmztype[] = "Aaa Aaa O0 00:00:00 AAA 0000";
  147.  
  148. isdate(date)
  149.     char date[];
  150. {
  151.  
  152.     return cmatch(date, ctype) || cmatch(date, tmztype);
  153. }
  154.  
  155. /*
  156.  * Match the given string (cp) against the given template (tp).
  157.  * Return 1 if they match, 0 if they don't
  158.  */
  159. cmatch(cp, tp)
  160.     register char *cp, *tp;
  161. {
  162.  
  163.     while (*cp && *tp)
  164.         switch (*tp++) {
  165.         case 'a':
  166.             if (!islower(*cp++))
  167.                 return 0;
  168.             break;
  169.         case 'A':
  170.             if (!isupper(*cp++))
  171.                 return 0;
  172.             break;
  173.         case ' ':
  174.             if (*cp++ != ' ')
  175.                 return 0;
  176.             break;
  177.         case '0':
  178.             if (!isdigit(*cp++))
  179.                 return 0;
  180.             break;
  181.         case 'O':
  182.             if (*cp != ' ' && !isdigit(*cp))
  183.                 return 0;
  184.             cp++;
  185.             break;
  186.         case ':':
  187.             if (*cp++ != ':')
  188.                 return 0;
  189.             break;
  190.         case 'N':
  191.             if (*cp++ != '\n')
  192.                 return 0;
  193.             break;
  194.         }
  195.     if (*cp || *tp)
  196.         return 0;
  197.     return (1);
  198. }
  199.  
  200. /*
  201.  * Collect a liberal (space, tab delimited) word into the word buffer
  202.  * passed.  Also, return a pointer to the next word following that,
  203.  * or NOSTR if none follow.
  204.  */
  205. char *
  206. nextword(wp, wbuf)
  207.     register char *wp, *wbuf;
  208. {
  209.     register c;
  210.  
  211.     if (wp == NOSTR) {
  212.         *wbuf = 0;
  213.         return (NOSTR);
  214.     }
  215.     while ((c = *wp++) && c != ' ' && c != '\t') {
  216.         *wbuf++ = c;
  217.         if (c == '"') {
  218.              while ((c = *wp++) && c != '"')
  219.                  *wbuf++ = c;
  220.              if (c == '"')
  221.                  *wbuf++ = c;
  222.             else
  223.                 wp--;
  224.          }
  225.     }
  226.     *wbuf = '\0';
  227.     for (; c == ' ' || c == '\t'; c = *wp++)
  228.         ;
  229.     if (c == 0)
  230.         return (NOSTR);
  231.     return (wp - 1);
  232. }
  233.